package jjwc_fsy;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

/**
 * 这个是用于管理http连接的连接类
 */
public class HttpManager {

  public static Map<String, HttpConnectMsg> httpClients = new ConcurrentHashMap<>();

  public static void main(String[] args) {
    try {
      String localhost = sendRequest("localhost", 55200, "/v1/vehicles", "test",false);
      System.out.println(localhost);
    }
    catch (IOException e) {
      System.out.println("连接失败，错误信息" + e.toString());
    }
  }

  /**
   * 创建一个连接管理器
   *
   * @param ipAddress
   * @param port
   * @param agv_id
   * @return
   */
  public static CloseableHttpClient createHttpClient(String ipAddress, int port, String agv_id) {

    HttpConnectMsg httpConnectMsg = httpClients.computeIfAbsent(ipAddress, (k) -> {
      PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
      connectionManager.setMaxTotal(20); // 最大连接数
      connectionManager.setDefaultMaxPerRoute(10); // 每个路由默认的最大连接数
      // 创建HttpClient实例
      CloseableHttpClient build = HttpClients.custom().setConnectionManager(connectionManager).build();
      return new HttpConnectMsg(build, ipAddress, agv_id);
    });
    return httpConnectMsg.getClient();
  }

  /**
   * 这是发送请求--请求小车的状态
   *
   * @param ipAddress：ip地址
   * @param port：端口号
   * @param path：请求路径需要携带
   * @param agvName：是否设置为长连接
   * @param isLongConnect：是否设置为长连接
   * @return 返回的是json
   * @throws IOException
   */
  public static String sendRequest(String ipAddress, int port, String path, String agvName,boolean isLongConnect)
      throws IOException {
    if (!path.startsWith("/")) {
      path = "/" + path;
    }
    CloseableHttpClient httpClient = createHttpClient(ipAddress, port, agvName);
    HttpGet request = new HttpGet("http://" + ipAddress + ":" + port + path);
//    RequestConfig requestConfig =  RequestConfig.custom().setConnectTimeout(2000).setMaxRedirects(1).build();
    RequestConfig requestConfig =  RequestConfig.custom().setConnectTimeout(100).setMaxRedirects(1).build();
    request.setConfig(requestConfig);
//    System.out.printf("发送【%s】请求，请求path：%s\n", "GET",  request.getURI().getPath());
    if (isLongConnect) {
      request.setHeader("Connection", "keep-alive");
    }
    try (CloseableHttpResponse response = httpClient.execute(request)) {
      return EntityUtils.toString(response.getEntity());
    }
  }

  public static String sendRequestAndClose(String ipAddress, int port, String path ) throws IOException {
    CloseableHttpClient minimal = HttpClients.createMinimal();
    HttpGet request = new HttpGet("http://" + ipAddress + ":" + port + path);
    System.out.printf("发送【%s】请求，请求path：%s\n", "GET",  request.getURI().getPath());
    try (CloseableHttpResponse response = minimal.execute(request)) {
      return EntityUtils.toString(response.getEntity());
    }
  }

  /**
   * 这是发送post请求
   * @param ipAddress
   * @param port
   * @param path
   * @param requestData
   * @param agvName
   * @return
   * @throws IOException
   */
  public static String sendRequestByPost(String ipAddress, int port, String path,
                                         String requestData, String agvName)
      throws IOException {
    if (!path.startsWith("/")) {
      path = "/" + path;
    }
    CloseableHttpClient httpClient = createHttpClient(ipAddress, port, agvName);
    HttpPost httpPost = new HttpPost("http://" + ipAddress + ":" + port + path);
    System.out.printf("发送【%s】请求，请求path：%s\n", "POST",  httpPost.getURI().getPath());
    httpPost.setHeader("Content-Type", "application/json");
    httpPost.setHeader("Connection", "keep-alive");
    StringEntity entity = new StringEntity(requestData);
    httpPost.setEntity(entity);
    try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
      return EntityUtils.toString(response.getEntity());
    }
  }

  /**
   * 用于查询小车状态
   * @param ipAddress
   * @param port
   * @param path
   * @param requestData
   * @return
   * @throws IOException
   */
  public static String sendRequestByPostAndClose(String ipAddress, int port, String path,
                                         String requestData)
      throws IOException {
    if (!path.startsWith("/")) {
      path = "/" + path;
    }
    CloseableHttpClient httpClient = HttpClients.createMinimal();
    HttpPost httpPost = new HttpPost("http://" + ipAddress + ":" + port + path);
    System.out.printf("发送【%s】请求，请求path：%s,请求参数为【%s】\n", "POST",  httpPost.getURI().getPath(),requestData);
    httpPost.setHeader("Content-Type", "application/json");
//    httpPost.setHeader("Connection", "keep-alive");
    StringEntity entity = new StringEntity(requestData);
    httpPost.setEntity(entity);
    try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
      return EntityUtils.toString(response.getEntity());
    }
  }





  /**
   * 用于删除http连接
   *
   * @param ipAddress
   * @return
   */
  public static void deleteHttpClient(String ipAddress) {
    HttpConnectMsg remove = httpClients.remove(ipAddress);
    if (remove != null) {
      CloseableHttpClient client = remove.getClient();
      try {
        client.close();
      }
      catch (IOException e) {
        System.out.println("连接早已关闭，重复关闭异常");
      }
      System.out.printf("关闭小车%s连接成功\n", remove.getAgv_id());
    }
  }
}

@Data
@AllArgsConstructor
class HttpConnectMsg {
  /**
   * 这是http请求的连接器，HttpClient会帮我们管理长连接
   */
  private CloseableHttpClient client;
  /**
   * 这是agv对应的ip
   */
  private String ip;
  /**
   * 这是agv对应在调度中的名字。
   */
  private String agv_id;
}


